using System.Linq;
using System.Windows;
using System.Windows.Controls;
using WPFTemplateLib.WpfHelpers;

namespace WPFTemplateLib.Controls.Panels
{
	/// <summary>
	/// [自定义控件] 自动在元素之间添加分隔线的 StackPanel
	/// <para/>已知问题：不能作为 ItemsControl 的 ItemsPanel，如果有该需求，可使用 <see cref="RenderedSeparatorStackPanel"/>。
	/// </summary>
	public class SeparatorStackPanel : StackPanel
	{
		#region 成员、构造

		/// <summary>
		/// 是否是内部添加或移除
		/// </summary>
		private bool _isAddOrRemoveInternal;
		/// <summary>
		/// 添加或移除的锁
		/// </summary>
		private object _lockerForAddOrRemove = new ();

		#endregion

		#region 依赖属性

		#region [依赖属性] 分隔线样式
		/// <summary>
		/// 分隔线样式
		/// </summary>
		public Style SeparatorStyle
		{
			get => (Style)GetValue(SeparatorStyleProperty);
			set => SetValue(SeparatorStyleProperty, value);
		}
		/// <summary>
		/// [依赖属性] 分隔线样式
		/// </summary>
		public static readonly DependencyProperty SeparatorStyleProperty =
			 DependencyProperty.Register(nameof(SeparatorStyle), typeof(Style), typeof(SeparatorStackPanel), new PropertyMetadata(null, SeparatorStyleChangedCallback));
		/// <summary>
		/// 分隔线样式 变动处理方法
		/// </summary>
		private static void SeparatorStyleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if(e.NewValue is Style style && style.TargetType == typeof(Separator))
			{
				((SeparatorStackPanel)d).SetSeparatorStyle(style);
			}
		}
		#endregion

		#region [依赖属性] 是否显示分隔线（默认 true）
		/// <summary>
		/// 是否显示分隔线
		/// </summary>
		public bool IsShowSeparator
		{
			get => (bool)GetValue(IsShowSeparatorProperty);
			set => SetValue(IsShowSeparatorProperty, value);
		}
		/// <summary>
		/// [依赖属性] 是否显示分隔线
		/// </summary>
		public static readonly DependencyProperty IsShowSeparatorProperty =
			 DependencyProperty.Register(nameof(IsShowSeparator), typeof(bool), typeof(SeparatorStackPanel), new PropertyMetadata(true, IsShowSeparatorChangedCallback));
		/// <summary>
		/// 是否显示分隔线 变动处理方法
		/// </summary>
		private static void IsShowSeparatorChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			SeparatorStackPanel panel = (SeparatorStackPanel)d;

			//当作为 ItemsControl 的 ItemsPanel 时，子元素由 ItemsControl 生成，禁止显式修改 Children。
			//作为 ItemsPanel 使用时不再抛异常；作为普通 StackPanel 使用时仍可自动插入分隔线。
			//如果需要在 ItemsControl 中显示分隔线，请用 ItemContainerStyle 或 ItemTemplate 中放置 Separator，或使用 AlternationIndex/Triggers 控制隔行分隔线；
			//或自定义一个 ItemsControl 自身去生成分隔项，而不是在 ItemsPanel 中直接操作 Children。
			if(panel.IsItemsHost)
			{
				return;
			}

			if(e.NewValue is bool isShow && isShow)
			{
				if(!panel.Children.IsExistsChild<Separator>())
				{
					var originChildren = panel.Children.FindChildren<UIElement>().ToList();

					lock(panel._lockerForAddOrRemove)
					{
						panel._isAddOrRemoveInternal = true;
					}

					for(int index = 0; index < originChildren.Count - 1; index++)
					{
						UIElement child = originChildren[index];
						int newIndex = panel.Children.IndexOf(child) + 1;
						Separator separator = panel.CreateNewSeparator();
						panel.Children.Insert(newIndex, separator);
					}

					lock(panel._lockerForAddOrRemove)
					{
						panel._isAddOrRemoveInternal = false;
					}
				}
			}
			else
			{
				lock(panel._lockerForAddOrRemove)
				{
					panel._isAddOrRemoveInternal = true;
				}

				for(int index = 0; index < panel.Children.Count; index++)
				{
					UIElement child = panel.Children[index];
					if(child is Separator separator)
					{
						panel.Children.Remove(separator);
					}
				}

				lock(panel._lockerForAddOrRemove)
				{
					panel._isAddOrRemoveInternal = false;
				}
			}
		}
		#endregion

		#endregion

		#region 方法

		/// <summary>
		/// 设置分隔线的样式
		/// </summary>
		/// <param name="style"></param>
		private void SetSeparatorStyle(Style style)
		{
			foreach(UIElement child in Children)
			{
				if(child.GetType() != typeof(Separator))
					continue;

				((Separator)child).Style = style;
			}
		}

		/// <inheritdoc />
		protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
		{
			base.OnVisualChildrenChanged(visualAdded, visualRemoved);

			// 当作为 ItemsControl 的 ItemsPanel 时，子元素由 ItemsControl 生成，禁止显式修改 Children
			if(_isAddOrRemoveInternal || !IsShowSeparator || IsItemsHost)
			{
				return;
			}

			var index = Children.Count - 1;

			if(visualAdded != null)
			{
				//Console.WriteLine("子元素被添加: " + visualAdded);
				if(index > 0 && Children[index - 1] is not Separator)
				{
					Separator separator = CreateNewSeparator();
					Children.Insert(index, separator);
				}
			}

			if(visualRemoved != null)
			{
				//Console.WriteLine("子元素被移除: " + visualRemoved);
				if(index > 0 && Children[index] is Separator separator)
				{
					Children.Remove(separator);
				}
			}
		}

		/// <summary>
		/// 创建新的分隔线
		/// </summary>
		/// <returns></returns>
		private Separator CreateNewSeparator()
		{
			var separator = new Separator();
			if(SeparatorStyle != null)
				separator.Style = SeparatorStyle;

			return separator;
		}

		#endregion
	}
}
